package gbase

import (
	"fmt"
	"strconv"
	"strings"

	"github.com/henrylee2cn/ameda"
)

type pathItem interface {
	int8 | int | int64 | string
}

// fmt1: ,1,2,3,4,
// fmt2: ,tony,lucy,scot,
type Path[T pathItem] string

// Deprecated: Use IsEmpty() instead
func (this Path[T]) Empty() bool {
	return this == "" || this == ","
}

func (p Path[T]) IsEmpty() bool {
	return p == "" || p == ","
}

func (this Path[T]) FromString(pathStr string) Path[T] {
	this = Path[T](pathStr)
	return this
}
func (this Path[T]) ToString() string {
	return string(this)
}

func (this Path[T]) RmHeadEnd() Path[T] {
	if len(this) > 0 {
		this = this[1:]
	}
	if len(this) > 0 {
		this = this[0 : len(this)-1]
	}
	return this
}

func (this Path[T]) ToList() (list []T, err error) {
	str := this.RmHeadEnd()
	if str == "" {
		return
	}
	strs := strings.Split(str.ToString(), ",")

	switch any(list).(type) {
	case []int64:
		for _, s := range strs {
			var v int64
			v, err = strconv.ParseInt(s, 10, 64)
			if err != nil {
				return nil, err
			}
			list = append(list, any(v).(T))
		}
	case []int:
		for _, s := range strs {
			var v int
			v, err = ameda.StringToInt(s)
			if err != nil {
				return nil, err
			}
			list = append(list, any(v).(T))
		}
	case []int8:
		for _, s := range strs {
			var v int8
			parsedInt, err := strconv.ParseInt(s, 10, 8)
			if err != nil {
				return nil, err
			}
			v = int8(parsedInt)
			list = append(list, any(v).(T))
		}
	case []string:
		for _, v := range strs {
			list = append(list, any(v).(T))
		}
	default:
		return nil, fmt.Errorf("unsupported type")
	}

	return list, nil
}

func (this Path[T]) MustToList() (list []T) {
	var err error
	list, err = this.ToList()
	if err != nil {
		panic(fmt.Sprintf("Path.MustToList failed,err:%s", err.Error()))
	}
	return
}

func (this Path[T]) FromList(list []T) Path[T] {
	if len(list) == 0 {
		return Path[T]("")
	}
	strList := make([]string, len(list))
	for i, v := range list {
		strList[i] = fmt.Sprintf("%v", v)
	}
	return Path[T](fmt.Sprintf(",%s,", strings.Join(strList, ",")))
}

func (this Path[T]) Has(v T) bool {
	return InArray(v, this.MustToList())
}

func (this Path[T]) Add(item T) Path[T] {

	//if this.Empty() {
	//	*this = Path[T](fmt.Sprintf(",%v,", item))
	//} else {
	//	*this = Path[T](fmt.Sprintf("%s%v,", *this, item))
	//}

	//ori
	if this.IsEmpty() {
		this = Path[T](fmt.Sprintf(",%v,", item))
	} else {
		this = Path[T](fmt.Sprintf("%s%v,", this, item))
	}
	return this
}

func (this Path[T]) Remove(item T) Path[T] {
	if this.Empty() || !this.Has(item) {
		return this // 如果路径为空或不包含该元素，直接返回原路径
	}

	// 去掉路径首尾的逗号
	str := this.RmHeadEnd().ToString()
	// 将路径分割为切片
	parts := strings.Split(str, ",")
	var newParts []string

	// 遍历切片，保留非目标元素
	for _, part := range parts {
		if fmt.Sprintf("%v", item) != part {
			newParts = append(newParts, part)
		}
	}

	// 重新拼接路径字符串
	return Path[T](fmt.Sprintf(",%s,", strings.Join(newParts, ",")))
}

// First 返回路径中的第一个元素
func (p Path[T]) First() T {
	if p.IsEmpty() {
		var zero T
		return zero
	}

	list := p.MustToList()
	if len(list) == 0 {
		var zero T
		return zero
	}

	return list[0]
}

// Last 返回路径中的最后一个元素
func (p Path[T]) Last() T {
	if p.IsEmpty() {
		var zero T
		return zero
	}

	list := p.MustToList()
	if len(list) == 0 {
		var zero T
		return zero
	}

	return list[len(list)-1]
}

// At 按索引值获取元素（索引从 0 开始）
// 如果索引越界或 Path 为空，返回零值
func (p Path[T]) At(index int) T {
	if p.IsEmpty() {
		var zero T
		return zero
	}

	list := p.MustToList()
	if index < 0 || index >= len(list) {
		var zero T
		return zero
	}

	return list[index]
}
